package edu.cmu.cs.stage3.alice.core.visualization;

import edu.cmu.cs.stage3.alice.core.Collection;
import edu.cmu.cs.stage3.alice.core.Model;
import edu.cmu.cs.stage3.alice.core.Variable;

public abstract class CollectionOfModelsVisualization extends edu.cmu.cs.stage3.alice.core.Visualization {
	private java.util.Vector m_bins = new java.util.Vector();

	//Rem @Override
	public void unhook( Model model ) {
		int i = indexOf( model, 0 );
		if( i != -1 ) {
			set( i, null );
		}
	}

	protected String getItemsName() {
		return "items";
	}
	private Variable m_itemsVariable = null;
	private Variable getItemsVariable() {
		if( m_itemsVariable == null ) {
			m_itemsVariable = (Variable)getChildNamed( getItemsName() );
		}
		return m_itemsVariable;
	}
	public Collection getItemsCollection() {
		return (Collection)getItemsVariable().value.getValue();
	}
	public Model[] getItems() {
		return (Model[])getItemsCollection().values.getArrayValue();
	}
	public void setItems( Model[] items ) {
		getItemsCollection().values.set( items );
	}

	private Model getPrototype() {
		return (Model)getChildNamed( "BinPrototype" );
	}
	private int getBinCount() {
		return m_bins.size();
	}
	private Model getBinAt( int i ) {
		return (Model)m_bins.get( i );
	}
	private void setBinAt( int i, Model bin ) {
		if( m_bins.size() == i ) {
			m_bins.addElement( bin );
		} else {
			if( m_bins.size() < i ) {
				m_bins.ensureCapacity( i+1 );
			}
			m_bins.set( i, bin );
		}
	}

	private void synchronize( Model[] curr ) {
		int binCount = getBinCount();
		for( int i=binCount-1; i>=curr.length; i-- ) {
			Model binI = getBinAt( i );
			m_bins.remove( binI );
		}
		Model prototype = getPrototype();
		if( prototype != null ) {
			for( int i=binCount; i<curr.length; i++ ) {
				Class[] share = { };
				String name = "Sub"+i;
				Model binI = (Model) getChildNamed( name );
				if( binI == null ) {
					binI = (Model)prototype.HACK_createCopy( name, this, -1, share, null );
				}
				setBinAt( i, binI );
			}
			binCount = getBinCount();
		}
	}

	public Model get( int i ) {
		return (Model)getItemsCollection().values.get( i );
	}
	public void set( int i, Model model ) {
		getItemsCollection().values.set( i, model );
	}
	public int indexOf( Model model, int from ) {
		return getItemsCollection().values.indexOf( model, from );
	}
	public int lastIndexOf( Model model, int from ) {
		return getItemsCollection().values.lastIndexOf( model, from );
	}
	public boolean contains( Model model ) {
		return getItemsCollection().values.contains( model );
	}
	public int size() {
		return getItemsCollection().values.size();
	}
	public boolean isEmpty() {
		return getItemsCollection().values.isEmpty();
	}

	//Rem @Override
	protected void loadCompleted() {
		super.loadCompleted();
		Collection collection = getItemsCollection();
		if( collection != null ) {
			collection.values.addPropertyListener( new edu.cmu.cs.stage3.alice.core.event.PropertyListener() {
				public void propertyChanging( edu.cmu.cs.stage3.alice.core.event.PropertyEvent propertyEvent ) {
				}
				public void propertyChanged( edu.cmu.cs.stage3.alice.core.event.PropertyEvent propertyEvent ) {
					CollectionOfModelsVisualization.this.synchronize( (Model[])propertyEvent.getValue() );
				}
			} );
			synchronize( getItems() );
		} else {
			System.err.println( "WARNING: collection is null " + this );
		}
	}
}
